home *** CD-ROM | disk | FTP | other *** search
- /*
- *
- * $Id: ibmpc.c,v 4.12 1996/03/15 07:41:11 hubert Exp $
- *
- * Program: IBM PC specific routine
- *
- *
- * Michael Seibel
- * Networks and Distributed Computing
- * Computing and Communications
- * University of Washington
- * Administration Builiding, AG-44
- * Seattle, Washington, 98195, USA
- * Internet: mikes@cac.washington.edu
- *
- * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
- *
- *
- * Pine and Pico are registered trademarks of the University of Washington.
- * No commercial use of these trademarks may be made without prior written
- * permission of the University of Washington.
- *
- * Pine, Pico, and Pilot software and its included text are Copyright
- * 1989-1996 by the University of Washington.
- *
- * The full text of our legal notices is contained in the file called
- * CPYRIGHT, included with this distribution.
- *
- */
-
- /*
- * The routines in this file provide support for the IBM-PC and other
- * compatible terminals. It goes directly to the graphics RAM to do
- * screen output. It compiles into nothing if not an IBM-PC driver
- */
-
- #include <stdio.h>
- #include <conio.h>
- #include <time.h>
- #include "osdep.h"
- #if IBMPC
- #define termdef 1 /* don't define "term" external */
- #include "pico.h"
- #include "estruct.h"
- #include "efunc.h"
- #include "edef.h"
-
- #ifdef ANSI
- int ibmmove(int, int);
- int ibmeeol(void);
- int ibmputc(int);
- int ibmoutc(char);
- int ibmeeop(void);
- int ibmrev(int);
- void beep(unsigned int, unsigned int);
- int cutebeep(void);
- int ibmbeep(void);
- int ibmopen(void);
- int ibmclose(void);
- #else
- int ibmmove();
- int ibmeeol();
- int ibmputc();
- int ibmoutc();
- int ibmeeop();
- int ibmrev();
- void beep();
- int cutebeep();
- int ibmbeep();
- int ibmopen();
- int ibmclose();
- #endif
-
-
- #define NROW 25 /* Screen size. */
- #define NCOL 80 /* Edit if you want to. */
- #define MARGIN 8 /* size of minimim margin and */
- #define SCRSIZ 64 /* scroll size for extended lines */
- #define MROW 2 /* rows in menu */
- #define NPAUSE 200 /* # times thru update to pause */
- #define BEL 0x07 /* BEL character. */
- #define ESC 0x1B /* ESC character. */
- #define SPACE 32 /* space character */
-
-
-
-
- #define SET_COLOR(fore,back) ((((back) & 0xf) << 4) | ((fore) & 0xf))
-
- int nfcolor = 7; /* current forground color */
- int nbcolor = 1; /* current background color */
- int rfcolor = 0; /* reverse forground color */
- int rbcolor = 3; /* reverse background color */
- unsigned cattr; /* current combined attribute */
-
- /*
- * Standard terminal interface dispatch table. Most of the fields point into
- * "termio" code.
- */
- TERM term = {
- NROW-1,
- NCOL,
- MARGIN,
- SCRSIZ,
- MROW,
- ibmopen,
- ibmclose,
- ttgetc,
- ibmputc,
- ttflush,
- ibmmove,
- ibmeeol,
- ibmeeop,
- ibmbeep,
- ibmrev
- };
-
-
- #ifdef DOS
- extern union REGS rg;
- static unsigned display_mode; /* */
- #endif
-
-
- static char *colist[] = {
- "black",
- "blue",
- "green",
- "cyan",
- "red",
- "magenta",
- "yellow",
- "white",
- "BLACK",
- "BLUE",
- "GREEN",
- "CYAN",
- "RED",
- "MAGENTA",
- "YELLOW",
- "WHITE" };
-
- /*
- * pico_setcolor - given the color name, return the color's value
- */
- int
- setcolor(s)
- char *s;
- {
- int i;
-
- for (i=0; i<16; i++)
- if (!strcmp(colist[i],s))
- return(i);
-
- return(7);
- }
-
-
- /*
- * pico_XXcolor() - each function sets a particular attribute
- */
- pico_nfcolor(s)
- char *s;
- {
- nfcolor = setcolor(s);
- }
-
- pico_nbcolor(s)
- char *s;
- {
- nbcolor = setcolor(s);
- }
-
- pico_rfcolor(s)
- char *s;
- {
- rfcolor = setcolor(s);
- }
-
- pico_rbcolor(s)
- char *s;
- {
- rbcolor = setcolor(s);
- }
-
- #ifdef OS2
- static VIOMODEINFO display_mode;
- static BYTE *oldscreen =NULL;
- static USHORT origRow, origCol;
- static USHORT origLen =0;
- #ifdef FASTVIO
- extern HMOU Mouse_Handle;
- extern int mouse_state;
- static int was_mouse_state=-1;
- static int _moved=0, _line=0, _col=0;
- static USHORT usVidbufLength =0;
- static USHORT usRows =0, usCols =0;
- static USHORT * pusVidBuffer =NULL;
- static USHORT fCell=(USHORT)-1,
- lCell=(USHORT)-1;
-
- static HEV hvUpdate =(HEV)0;
- static HMTX hxUpdate =(HMTX)0;
- static TID threadID;
- static NOPTRRECT noptr = { 0, 0, (USHORT)-1, (USHORT)-1 };
-
- static void update_thread(ULONG args)
- {
- while (DosWaitEventSem(hvUpdate, -1)==0) {
- DosResetEventSem(hvUpdate, &args);
- if (fCell!=(USHORT)-1) {
- DosRequestMutexSem(hxUpdate,-1);
- if (was_mouse_state && Mouse_Handle!=(HMOU)-1)
- MouRemovePtr(&noptr, Mouse_Handle);
- /* Update the screen, if required */
- VioShowBuf(fCell*2,(lCell-fCell+1)*2, 0);
- fCell=lCell=(USHORT)-1;
- DosReleaseMutexSem(hxUpdate);
- if (mouse_state && Mouse_Handle!=(HMOU)-1)
- MouDrawPtr(Mouse_Handle);
- }
- else if (mouse_state != was_mouse_state && Mouse_Handle!=(HMOU)-1) {
- if (mouse_state)
- MouDrawPtr(Mouse_Handle);
- else
- MouRemovePtr(&noptr, Mouse_Handle);
- }
- was_mouse_state=mouse_state;
- if (_moved) {
- _moved=0;
- VioSetCurPos((USHORT)_line,(USHORT)_col,0);
- }
- DosSleep(1);
- }
- }
-
- static void vidCell(USHORT row, USHORT col)
- {
- USHORT cell=(row*usCols)+col;
-
- DosRequestMutexSem(hxUpdate,-1);
- /* Always update first cell */
- if (fCell==(USHORT)-1)
- fCell=lCell=cell;
- else {
- /* Otherwise stretch limits if necessary */
- if (cell<fCell)
- fCell=cell;
- if (cell>lCell)
- lCell=cell;
- }
- DosReleaseMutexSem(hxUpdate);
- }
-
- /* These seek to do minimal screen update
- * by keeping track of the first and last
- * cells written to the video buffer
- */
-
- void vidUpdate()
- {
- if (hvUpdate == (HEV)0) {
- VIOMODEINFO mi;
-
- DosCreateEventSem(NULL, &hvUpdate, 0, FALSE);
- DosCreateMutexSem(NULL, &hxUpdate, 0, FALSE);
- DosCreateThread(&threadID,update_thread,0,0,8192);
- mi.cb = sizeof mi;
- VioGetMode(&mi, 0);
- noptr.cRow = mi.row-1;
- noptr.cCol = mi.col-1;
- }
- DosPostEventSem(hvUpdate);
- }
-
- static void vidArea(USHORT frow, USHORT fcol, USHORT lrow, USHORT lcol)
- {
- vidCell(frow,fcol);
- vidCell(lrow,lcol);
- }
- #endif
- #endif
-
-
- /*
- * ibmmove - Use BIOS video services, function 2h to set cursor postion
- */
- ibmmove(row, col)
- int row, col;
- {
- #ifdef OS2
- #ifdef FASTVIO
- if (_line!=row || _col!=col) {
- _line=row;
- _col=col;
- _moved=1;
- }
- #else
- VioSetCurPos((USHORT)row, (USHORT)col, 0);
- #endif
- #else
- rg.h.ah = 2; /* set cursor position function code */
- rg.h.bh = 0; /* set screen page number */
- rg.h.dl = col;
- rg.h.dh = row;
- int86(BIOS_VIDEO, &rg, &rg);
- #endif
- }
-
-
- /*
- * ibmeeol - erase to the end of the line
- */
- ibmeeol()
- {
- #ifdef OS2
- USHORT row, col;
- BYTE chattr[2];
- chattr[0] = ' ';
- chattr[1] = (BYTE)cattr;
-
- #ifdef FASTVIO
- row=(USHORT)_line;
- col=(USHORT)_col;
- vidCell(row,col);
- vidCell(row,usCols-1);
- row=(row*usCols)+col;
- col=usCols-col;
- while(col--)
- pusVidBuffer[row++] = *(USHORT *)chattr;
- #else
- /* find the current cursor position */
- VioGetCurPos(&row, &col, 0);
- VioWrtNCell(chattr, NCOL-col, row, col, 0);
- #endif
- #else
- int col, row, page;
-
- /* find the current cursor position */
- rg.h.ah = 3; /* read cursor position function code */
- int86(BIOS_VIDEO, &rg, &rg);
- page = rg.h.bh;
- col = rg.h.dl; /* record current column */
- row = rg.h.dh; /* and row */
-
- rg.h.ah = 0x09; /* write char to screen with new attrs */
- rg.h.al = ' ';
- rg.h.bl = cattr;
- rg.h.bh = page;
- rg.x.cx = NCOL-col;
- int86(BIOS_VIDEO, &rg, &rg);
- #endif
- }
-
-
- /*
- * ibmputc - put a character at the current position in the
- * current colors
- */
- ibmputc(ch)
- int ch;
- {
- #ifdef OS2
- USHORT row, col;
-
- /* first, get current position */
- #ifdef FASTVIO
- row=(USHORT)_line;
- col=(USHORT)_col;
- #else
- VioGetCurPos(&row, &col, 0);
- #endif
- if (ch == '\b') {
- if (col > 0)
- ibmmove(row, --col);
- }
- else {
- BYTE chattr[2];
- chattr[0]=(BYTE)ch;
- chattr[1]=(BYTE)cattr;
- #if FASTVIO
- vidCell(row,col);
- pusVidBuffer[(row*usCols)+col] = *(USHORT *)chattr;
- if (col < usCols)
- #else
- VioWrtNCell(chattr, 1, row, col, 0);
- if (col < NCOL)
- #endif
- ibmmove(row, ++col);
- }
- #else
- int col, row, page;
-
- rg.h.ah = 0x03; /* first, get current position */
- int86(BIOS_VIDEO, &rg, &rg);
- page = rg.h.bh;
- row = rg.h.dh;
- col = rg.h.dl;
-
- if(ch == '\b'){
- if(col > 0) /* advance the cursor */
- ibmmove(row, --col);
- }
- else{
- rg.h.ah = 0x09; /* write char to screen with new attrs */
- rg.h.al = ch;
- rg.h.bl = cattr; /* inverting if needed */
- rg.h.bh = page;
- rg.x.cx = 1; /* only once */
- int86(BIOS_VIDEO, &rg, &rg);
-
- if(col < 80) /* advance the cursor */
- ibmmove(row, ++col);
- }
- #endif
- }
-
-
- /*
- * ibmgetc - output a single character with the right attributes, but
- * don't advance the cursor
- */
- ibmgetc(c)
- char *c;
- {
- #ifdef OS2
- /* first, get current position */
- #if FASTVIO
- *c=(BYTE)pusVidBuffer[(_line*usCols)+_col];
- #else
- USHORT row, col, n = 1;
-
- VioGetCurPos(&row, &col, 0);
- VioReadCharStr(c, 1, &n, row, col, 0);
- #endif
- #else
- rg.h.ah = 8; /* vid services, read char at cursor */
- rg.h.bh = 0;
- int86(0x10, &rg, &rg);
- *c = rg.h.al;
- #endif
- }
-
-
- /*
- * ibmeeop - clear from cursor to end of page
- */
- ibmeeop()
- {
- #ifdef OS2
- #if FASTVIO
- USHORT atofs;
- #endif
- BYTE chattr[2];
- chattr[0] = ' ';
- chattr[1] = (BYTE)cattr;
-
- #ifdef FASTVIO
- vidArea(0,0,usRows-1,usCols-1);
- for (atofs=0; atofs < usVidbufLength;++atofs)
- pusVidBuffer[atofs] = *(USHORT *)chattr;
- #else
- VioScrollUp(0, 0, -1, -1, -1, chattr, 0);
- #endif
- #else
- rg.h.ah = 6; /* scroll page up function code */
- rg.h.al = 0; /* # lines to scroll (clear it) */
- rg.x.cx = 0; /* upper left corner of scroll */
- rg.x.dx = (term.t_nrow << 8) | (term.t_ncol - 1);
- rg.h.bh = cattr;
- int86(BIOS_VIDEO, &rg, &rg);
- #endif
- ibmmove(0, 0);
- }
-
-
- /*
- * ibmrev - change reverse video state
- */
- ibmrev(state)
- int state;
- {
- cattr = (state) ? SET_COLOR(rfcolor, rbcolor)
- : SET_COLOR(nfcolor, nbcolor);
- }
-
-
- /*
- * getrevstate - return the current reverse state
- */
- getrevstate()
- {
- return(cattr == SET_COLOR(rfcolor, rbcolor));
- }
-
-
- /*
- * beep - make the speaker sing!
- */
- void
- beep(freq, dur)
- unsigned freq, dur;
- {
- #ifdef OS2
- if (freq)
- DosBeep(freq, dur);
- #else
- unsigned oport;
-
- if(!freq)
- return;
-
- freq = (unsigned)(1193180 / freq);
- /* set up the timer */
- outp(0x43, 0xb6); /* set timer channel 2 registers */
- outp(0x42, (0xff&freq)); /* low order byte of count */
- outp(0x42, (freq>>8)); /* hi order byte of count */
-
- /* make the sound */
- oport = inp(0x61);
- outp(0x61, oport | 0x03);
- ssleep((clock_t)((dur < 75) ? 75 : dur));
- outp(0x61, oport);
- #endif
- }
-
-
- /*
- * cutebeep - make the speeker sing the way we want!
- */
- cutebeep()
- {
- beep(575, 50);
- #ifndef OS2
- ssleep((clock_t)25);
- #endif
- beep(485, 90);
- }
-
-
- /*
- * ibmbeep - system beep...
- */
- ibmbeep()
- {
- cutebeep();
- }
-
-
- /*
- * enter_text_mode - get current video mode, saving to be restored
- * later, then explicitly set 80 col text mode.
- *
- * NOTE: this gets kind of weird. Both pine and pico call this
- * during initialization. To make sure it's only invoked once
- * it only responds if passed NULL which pico only does if not
- * called from in pine, and pine does all the time. make sense?
- * thought not.
- */
- void
- enter_text_mode(p)
- PICO *p;
- {
- #ifdef OS2
- if (!p) {
- #ifdef FASTVIO
- ULONG pBuf;
- #endif
- display_mode.cb = sizeof display_mode;
- VioGetMode(&display_mode, 0);
- term.t_ncol = display_mode.col;
- term.t_nrow = display_mode.row - 1;
- origLen = display_mode.row * display_mode.col * sizeof(USHORT);
- if (oldscreen)
- free(oldscreen);
- oldscreen = malloc(origLen);
- if (oldscreen)
- VioReadCellStr(oldscreen, &origLen, 0, 0, 0);
- VioGetCurPos(&origRow, &origCol, 0);
- #ifdef FASTVIO
- _line=origRow;
- _col=origCol;
- #endif
- #ifdef FASTVIO
- usRows = display_mode.row;
- usCols = display_mode.col;
- VioGetBuf(&pBuf,&usVidbufLength,0);
- pusVidBuffer = _emx_16to32((_far16ptr)pBuf);
- /* OS2 2.1+ VIO bug (viobuf not initialised) workaround */
- memcpy(pusVidBuffer,oldscreen,usVidbufLength);
- usVidbufLength /= 2; /* Cells, not bytes */
- #endif
- }
- #else
- static int i = 0;
- if(!p && !i++){
- rg.h.ah = 0x0f; /* save old mode */
- int86(BIOS_VIDEO, &rg, &rg);
- display_mode = rg.h.al;
-
- rg.h.ah = 0; /* then set text mode */
- rg.h.al = 2;
- int86(BIOS_VIDEO, &rg, &rg); /* video services */
- }
- #endif
- }
-
-
- /*
- * exit_text_mode - leave text mode by restoring saved original
- * video mode.
- */
- void
- exit_text_mode(p)
- PICO *p;
- {
-
- #ifdef OS2
- if (!p) {
- turnmouseoff(); /* Make sure mouse is off while display is updated */
- VioSetMode(&display_mode, 0);
- if (!oldscreen)
- {
- ibmeeop();
- VioSetCurPos(display_mode.row-1, 0, 0);
- }
- else
- {
- VioWrtCellStr(oldscreen, origLen, 0, 0, 0);
- VioSetCurPos(origRow, origCol, 0);
- }
- }
- #else
- static int i = 0;
- if(!p && !i++){ /* called many, invoke once! */
- rg.h.ah = 0; /* just restore old mode */
- rg.h.al = display_mode;
- int86(BIOS_VIDEO, &rg, &rg);
- }
- #endif
- }
-
-
- /*
- * ibmopen - setup text mode and setup key labels...
- */
- ibmopen()
- {
-
- enter_text_mode(Pmaster);
-
- cattr = SET_COLOR(nfcolor, nbcolor);
- revexist = TRUE;
- inschar = delchar = 0;
-
- ttopen();
- }
-
-
- ibmclose()
- {
- #if COLOR
- ibmfcol(7);
- ibmbcol(0);
- #endif
- #ifdef MOUSE
- mouseoff();
- #endif
- exit_text_mode(Pmaster);
-
- ttclose();
- }
- #endif
-
-